/**
 * @file Implements SwitchMap.
 * @author Zmei Zelen <zmei.zelen@gmail.com>
 */


function SwitchMap() {
    this.on = new EventSet();
    this.on.add(['on', 'off', 'up', 'down']);   
    this.states = {};
    this.switches = {};
    return this;
};


SwitchMap.prototype.addSwitch = function (which, state) {
    switch (typeof which) {
        case 'string':
        case 'number':
            this.switches[which] = Boolean(state);
            break;
        case 'object':
            if (which instanceof Array) {
                for (var id = 0, length = which.length; id < length; id++) {
                    this.switches[which[id]] = Boolean(state);                    
                }
            } else {
                for (var id in which) {
                    this.switches[id] = Boolean(which[id]);
                }
            }
            break;
    }
};


SwitchMap.prototype.toggle = function (info, state) {
    if (typeof info === 'string') {
        info = { which: info, time: new Date().getTime() };
    }
    if (info.which in this.switches) {
        this.switches[info.which] = state !== undefined 
            ? Boolean(state) : !this.switches[info.which]; 
        this.on.fire(this.switches[info.which] ? 'on' : 'off', info);
    }
};


SwitchMap.prototype.addSource = function(down, up, signalMap) {    
    down((function(info) {            
        if (signalMap !== undefined) info.which = signalMap[info.which];        
        if (info.which !== undefined) {            
            info.which = info.which.toString(); 
            this.set(info);
            this.toggle(info);
        }
    }).bind(this));
    
    up((function(info) {
        if (signalMap !== undefined) info.which = signalMap[info.which];
        if (info.which !== undefined) {            
            info.which = info.which.toString();      
            this.clear(info);
        }
    }).bind(this));
};


SwitchMap.prototype.isOn = function(which) {
    return which in this.switches && this.switches[which];
};


SwitchMap.prototype.isSet = function(which) {
    return which in this.states && this.states[which];
};


SwitchMap.prototype.set = function(info) {
    if (typeof info === 'string') {
        info = { which: info, time: new Date().getTime() };
    }
    if (!this.states[info.which]) {                 
        this.on.fire('down', info);                
    }
    this.states[info.which] = true;
};


SwitchMap.prototype.clear = function (info) {
    if (typeof info === 'string') {
        info = { which: info, time: new Date().getTime() };
    }
    if (this.states[info.which] !== undefined && this.states[info.which]) {
        this.on.fire('up', info);                
    }
    this.states[info.which] = false;
};